home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / unix / uucp106d / part09 < prev    next >
Internet Message Format  |  1990-06-28  |  49KB

  1. Path: xanth!cs.odu.edu!Amiga-Request
  2. From: Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator)
  3. Newsgroups: comp.sources.amiga
  4. Subject: v90i187: UUCP 1.06D - UNIX compatible uucp/news/mail system, Part09/12
  5. Message-ID: <12978@xanth.cs.odu.edu>
  6. Date: 28 Jun 90 12:23:22 GMT
  7. Sender: news@cs.odu.edu
  8. Reply-To: Matt Dillon <@uunet.uu.net:overload!dillon>
  9. Lines: 1700
  10. Approved: tadguy@cs.odu.edu (Tad Guy)
  11. X-Mail-Submissions-To: Amiga@cs.odu.edu
  12. X-Post-Discussions-To: comp.sys.amiga
  13.  
  14. Submitted-by: Matt Dillon <@uunet.uu.net:overload!dillon>
  15. Posting-number: Volume 90, Issue 187
  16. Archive-name: unix/uucp-1.06d/part09
  17.  
  18. #!/bin/sh
  19. # This is a shell archive.  Remove anything before this line, then unpack
  20. # it by saving it into a file and typing "sh file".  To overwrite existing
  21. # files, type "sh file -c".  You can also feed this as standard input via
  22. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  23. # will see the following message at the end:
  24. #        "End of archive 9 (of 12)."
  25. # Contents:  uucp2/src/dmail/dmail.help uucp2/src/news/rnews.c
  26. # Wrapped by tadguy@xanth on Thu Jun 28 08:21:33 1990
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f 'uucp2/src/dmail/dmail.help' -a "${1}" != "-c" ; then 
  29.   echo shar: Will not clobber existing file \"'uucp2/src/dmail/dmail.help'\"
  30. else
  31. echo shar: Extracting \"'uucp2/src/dmail/dmail.help'\" \(23728 characters\)
  32. sed "s/^X//" >'uucp2/src/dmail/dmail.help' <<'END_OF_FILE'
  33. X
  34. X$Header: Beta:src/uucp/src/dmail/RCS/dmail.help,v 1.1 90/02/02 12:03:57 dillon Exp Locker: dillon $
  35. X
  36. X'help TOPIC' for more information on a command.  Many commands take
  37. Xmessage numbers or message lists:
  38. X    [msg]    is an optionaly specified message number (usually the
  39. X        operation is on the current message if no number is
  40. X        specified)
  41. X    <list>    is an optionaly specified message list.  Message lists
  42. X        consists of number ranges of the form N -N N- or N-N, and
  43. X        keywords (help keywords)
  44. X
  45. X
  46. XOTHER HELP AVAILABLE (in addition to the commands):
  47. X    pager sendmail tilde header newmail keywords enviroment
  48. X
  49. XDMAIL written by Matthew Dillon, U.C. Berkeley -UCF
  50. X
  51. X(C)Copyright 1985-1989 by Matthew Dillon
  52. X
  53. X.pager
  54. Xset page [rows/command]
  55. X
  56. X    'page' is a SET variable which determines the type of paging list and
  57. Xdisplay commands will use.  If not defined, no filter is used.    If a numerical
  58. Xvalue (i.e. 24) is specified, the page length will be set to that value and
  59. Xa rather stupid, simple internal paging routine will be used.  If the
  60. Xvariable is set to an alpha-numeric string, output will be piped through
  61. Xthat filter.  For instance:
  62. X
  63. X    unset page        -no paging
  64. X    set page more        -use more filter
  65. X    set page page        -use 'page' filter
  66. X    set page > x        -redirect to a file (be careful)
  67. X    set page 24        -use internal paging, page length 24 rows.
  68. X
  69. X    For internal paging, use <return> to continue, or your INTR
  70. Xcharacter to break out.  Note that if you have paging set to a program,
  71. Xresponse time may be slower because dmail must execute that program.
  72. X
  73. X.sendmail
  74. Xset sendmail sendmail-path
  75. X
  76. X    Inform DMAIL as to where the sendmail program is.  The default
  77. X(variable unset) is /usr/lib/sendmail.  This variable is useful only for
  78. Xthose of us who like to hack-up our own sendmail.
  79. X
  80. X.tilde
  81. X~ ~user directory expansion
  82. X
  83. X    In all expressions except those within double quotes, the tilde
  84. X`~` will be expanded to either your home directory, or the directory of
  85. Xa specified user, depending.  Note that '*' and '?' are not expanded by
  86. XDMAIL, though they will be by any shell commands you execute.
  87. X
  88. X    It is probably a good idea to use ~ in any aliases, etc... in case
  89. Xyou change directories using the 'cd' command.
  90. X
  91. X    alias resource source ~/.dmailrc        -example using ~
  92. X
  93. X.header
  94. Xset header filepath
  95. X
  96. X    Set the location of your header file, which will appended to the
  97. Xscratch mail file before you are placed in the editor (usually vi).
  98. X
  99. X    set header ~/.header            -set header file to ~/.header
  100. X    unset header                -no header file
  101. X
  102. X.newmail
  103. XWhen new mail comes in:
  104. X
  105. X    Whenever newmail arrives, it will be automatically incorporated into
  106. Xa running DMAIL.  However, to see it, you must 'select all' (or select on
  107. Xanything that would include it).
  108. X
  109. X.keywords
  110. X.range
  111. X.message
  112. XKEYWORDS, MESSAGE LISTS
  113. X
  114. X    Many commands in DMAIL require a range of messages be given.  A Range
  115. Xconsists of message numbers (3 4 5), message ranges (1-45 -9 9-), and
  116. Xkeywords.  Keywords select certain messages from the entire SELECTED list:
  117. X
  118. X    all        -All messages
  119. X    tag        -All TAGGED messages
  120. X    mark        -All MARKED (read) messages
  121. X    deleted     -All DELETED messages
  122. X    written     -All WRITTEN messages
  123. X    untag        -All messages NOT TAGGED
  124. X    unmark        -All messages NOT MARKED (i.e. read)
  125. X    undeleted    -All messages NOT DELETED
  126. X    unwritten    -All messages NOT WRITTEN
  127. X
  128. X    Only the first three letters need be specified.  For instance, the
  129. X'all' keyword selects all the messages currently selected.  You could select
  130. Xon some subject, say, and then 'delete all'.
  131. X
  132. X    The message number 0 refers to the last message. the 'undeleted'
  133. Xkeyword exists only for completeness; you will probably never use it.
  134. X
  135. X.ver
  136. X.version
  137. XVER
  138. X
  139. X    returns the version number.
  140. X
  141. X.if
  142. X.else
  143. X.endif
  144. XIF [!]variable
  145. XELSE
  146. XENDIF
  147. X
  148. X    Conditionals.  Example:
  149. X
  150. X    if verbose
  151. X        .... do stuff if the variable exists
  152. X    else
  153. X        ... do stuff if the variable does not exist
  154. X    endif
  155. X    if !page; echo no page variable; endif
  156. X
  157. X.nobreak
  158. X.breakok
  159. XNOBREAK
  160. XBREAKOK
  161. X
  162. X    Disable or Enable your INTR key.  This command is stackable, thus
  163. Xthere is no problem with recursive aliases which use it.  Be careful that
  164. Xyou match any NOBREAK to a BREAKOK, or you may accidently put yourself into
  165. XNOBREAK mode (and a single BREAKOK may not fix it because it's stackable).
  166. X
  167. X    A good example would be a command which needs the page variable set
  168. Xfor the duration... say an alias to TYPE to a file:
  169. X
  170. Xalias file "%_a nobreak; set _b $page; set page cat > $_a; type; set page $_b; unset _b; breakok"
  171. X
  172. X    You can see that if the user were to hit his INTR character at the
  173. Xwrong time, the page variable would be incorrectly set.  The nobreak/breakok
  174. Xcommands fix this problem.  For simplicity, most people don't bother with
  175. Xbreak/nobreak, as it clutter's aliases up.
  176. X
  177. X.delete
  178. XDELETE <message list>
  179. X
  180. X    Mark the specified messages for deletion.  They will no longer show up
  181. Xon LISTings, (gaps will appear in message numbering).  However, you can
  182. Xstill TYPE them, if you remember the message number, and you can always
  183. XUNDELETE them.    Remember that the particular message # you've deleted
  184. Xmay be different if you change the SELECT parameters.  For example,
  185. Xmessage #3 selecting 'To' & 'foo' may actually be message #45 when you
  186. Xare selecting ALL (see SELECT).  Upon a QUIT, messages marked for
  187. Xdeletion are actually deleted from the mail file.
  188. X
  189. X.undelete
  190. XUNDELETE   <message list>
  191. X
  192. X    UNDELETES messages.  Without arguments, UNDELETE will
  193. Xrestore the last message you deleted.  Specifying 'all' (undelete all), will
  194. Xundelete any deleted messages in the currently selected message list.
  195. X
  196. X.header
  197. XHEADER [message]
  198. X
  199. X    Display the entire header of a message.  This does not cause the
  200. Xmessage to be marked 'read'.  TYPE, on the other hand, only displays
  201. Xheader information specified by SETLIST.
  202. X
  203. X.type
  204. XTYPE [message]
  205. X
  206. X    Type the text of a message.  Only header fields defined by SETLIST
  207. Xare displayed.    Otherwise, only the text is displayed.    This marks
  208. Xthe particular message as 'read', and also makes that message the
  209. Xcurrent message.
  210. X
  211. X.echo
  212. XECHO [string]
  213. X
  214. X    Echo the given string onto the screen.
  215. X
  216. X.go
  217. XGO #
  218. X    go to a message, don't type it out or anything.  Remember that you
  219. Xcan go to the last message by using the message # 0.  By placing a keyword
  220. X(help range), you can go to the first TAGGED message, etc...
  221. X
  222. X.reply
  223. X.Reply
  224. XREPLY
  225. X
  226. X    Reply to the current letter.  There are two forms of 'reply'.  The
  227. Xfirst does not include the senders original letter, the second does.
  228. XIn both cases, Dmail will place you in VI, with the To:, Cc:, and
  229. Xsubject lines filled out.  The second form is 'Reply', with an
  230. Xupper case 'R'.  This form includes the sender's message shifted to
  231. Xthe right with '>'s on the left hand side.  See FORWARD for another
  232. Xmethod of replying to mail.
  233. X
  234. X    In any case, you may get the sender's letter by reading the file '#'
  235. Xfrom VI.  That sequence would be ':r\\#'
  236. X
  237. X    See MAIL for more information on VI
  238. X
  239. X.forward
  240. XFORWARD [user user user....]
  241. X
  242. X    Forward the current message to a list of users.  The sender's
  243. Xentire message is placed in the text portion.  The To: field will
  244. Xcontain the user's named above, and the Subject: field will contain
  245. Xa 'Fo:' (you append your own subject)
  246. X
  247. X    See MAIL for more information on VI
  248. X
  249. X.mail
  250. XMAIL [user user user user...]
  251. X
  252. X    Mail to [users].  You are given a VI to work from, and may modify
  253. Xany of the header fields.  the From: field is inserted automatically
  254. Xby SENDMAIL, but you can overide it if you wish.
  255. X
  256. X    Quitting out of VI without writing the output file will cause an
  257. Xabort, and no mail will be sent.   Additionaly, you may use the 'vibreak'
  258. Xvariable to enable your INTR character (usually CTL-C) to break you out of
  259. XVI.
  260. X
  261. X    When modifying the users list in To and Cc fields, remember that
  262. Xthey should be all comma delimited, or none comma delimited.
  263. X
  264. X.select
  265. XSELECT ALL
  266. XSELECT Field  match match match match...
  267. XSELECT Field  !match
  268. XSELECT Field  match match match , Field match , .....
  269. X
  270. X    Select what you want to look at.  Select will take the field header
  271. Xyou supply and attempt to match arguments with that field in the mail
  272. Xfile.  You can then work on the selected material as if the rest of
  273. Xyour mail didn't exist.  For instance, 'select To dillon', will select
  274. Xall messages addressed to you.    Note that case is checked for the
  275. XFIELD-HEADER, but not for arguments, so the latter will also find
  276. Xanything addressed to Dillon or DILLON.  You only have to give a
  277. Xpartial match, so 'select To di' would work just as well.
  278. X
  279. X    Select then, allows you to quickly find what you want even though
  280. Xyou may have 12000 messages (though it may take a while with that many)
  281. XYou may also specify what you DON'T want to select on:
  282. X
  283. X select To !foo
  284. X
  285. Xwill select all letters not addressed to 'foo'.  You may select on any
  286. Xfield you wish.  At any time, you may say 'select ALL' to select the
  287. Xentire message list.  Use RESELECT to select on the current message
  288. Xlist.  SELECT always selects from the entire message-list
  289. X
  290. X select Cc hack , To hack
  291. X
  292. Xwill select any mail with Cc or To fields containing hack.  You may
  293. Xhave as many comma operators as you wish.  The comma must be a field
  294. Xof its own (spaces on either side... will be fixed in a later version)
  295. X
  296. X.reselect
  297. XRESELECT ALL
  298. XRESELECT Field    match match match match...
  299. XRESELECT Field    !match
  300. X
  301. X    SEE SELECT.  Reselect allows you to CONTINUE to narrow down a topic
  302. Xor whatever.  It will select on the current message list (which you have
  303. Xalready narrowed down with SELECT or RESELECT).
  304. X
  305. X.defer
  306. XDEFER
  307. X
  308. X    Deselects any marked messages .. messages marked as 'read'.  This is
  309. Xas if you did a RESELECT on all unread messages in the current select field.
  310. XThus, the messages will be renumbered.    To see these messages again, you must
  311. Xuse SELECT.
  312. X
  313. X.rlist <num>
  314. XRLIST <num>        -<num> > 0 (next N), < 0 (prev N).
  315. XRLIST            -Lists next 20 (or previous 20 if near the end)
  316. X
  317. X    Relative list.    See LIST for details of the list command.  This
  318. Xcommand will display the next <num> messages beginning at the current
  319. Xmessage.  If <num> is negative, it displays the previous 20 ending at
  320. Xthe current message.  If there are not enough messages remaining in the
  321. Xforward or reverse direction, it lists in the opposite direction to try
  322. Xto bring the total messages listed to <num>
  323. X
  324. X.list
  325. XLIST <message list>
  326. XLIST            -Lists all selected messages
  327. X
  328. X    Display header information on a message as specified by SETLIST,
  329. Xin a one line per message format.  The default lists ALL messages.
  330. X
  331. XLeftword flags:    r    -indicates message has been read.  Message will be
  332. X             moved to the destination file on QUIT
  333. X           >    -indicates message is the current message
  334. X           w    -indicates message has been written to a file.
  335. X             Message will be deleted from source file on QUIT
  336. X           T    -indicates message has been taged by the user
  337. X
  338. X.next
  339. XNEXT
  340. X
  341. X    Execute TYPE or HEADER for the next message, depending on which of
  342. XTYPE or HEADER was last executed by you
  343. X
  344. X._next
  345. X_NEXT
  346. X
  347. X    Go to next message, do not print it out.
  348. X
  349. X.back
  350. XBACK
  351. X
  352. X    Execute TYPE or HEADER for the previous message, depending on which
  353. Xof TYPE or HEADER was last executed by you
  354. X
  355. X._back
  356. X_BACK
  357. X
  358. X    Go to previous message, do not print it out.
  359. X
  360. X.db
  361. XDB
  362. X    Delete the current message, type (or header) the previous message.
  363. XThis command could not be implemented with "del;prev" due to a special case
  364. Xwhen one is on the last message.
  365. X
  366. X.dt
  367. XDT
  368. X    Delete current message, type (or header) next message.  This command
  369. Xwill warn you when you reach the end of the message list.
  370. X
  371. X    References: DELETE and NEXT
  372. X
  373. X.enviroment
  374. XENVIROMENT VARIABLE ACCESS
  375. X
  376. X    Access may be gained to enviroment variables by using $$ instead of
  377. X    a single $.  For example:  echo $$USER
  378. X
  379. X    'help dmail' for command line options,
  380. X    'help set'   for description of special variables
  381. X
  382. X.set
  383. XSET [variable [string]]
  384. X
  385. X    see 'enviroment' for enviroment variables
  386. X
  387. X    With no arguments, SET prints out all currently active variables.
  388. XNote that this variable list is a different list than the ALIAS list.  With
  389. Xone argument, the specified variable is displayed if it exists, or created
  390. Xif it doesn't.  With more than one argument, the specified variable is set
  391. Xto the specified string.  Variables may be references on the command line by
  392. X$variable .  The variable's contents will replace the reference.  Unlike
  393. Xaliases, however, variable substitutions may take place anywhere on the
  394. Xcommand line rather than substitute just the command name.  Note also that
  395. Xif you use a $ substitution for an argument of a command, the entire
  396. Xvariable's contents is ONE argument (i.e. if a = "b c d", and you say
  397. Xsomething like: 'unset $a', it would attempt to unset a single variable
  398. Xwhos name is "b c d".
  399. X
  400. X    There are several reserved SET variables, which define options in
  401. XDMAIL.    Changing these will modify the option:
  402. X
  403. X    page        set paging on or to a specific command (i.e. more)
  404. X    sendmail    set the path to the sendmail program
  405. X    vibreak     enable your INTR character even when in VI.
  406. X    verbose     reflects verbose option to sendmail
  407. X    comlinemail    set when dmail executed w/ command line mailing list
  408. X    header        header file to append to any messages you send.
  409. X    ask        ask what to do after vi'ing mail
  410. X    archive     file to archive any mail you send out in.
  411. X    _headchar    string used to precede included text, default ">"
  412. X    replyfields    fields to search to find the reply path
  413. X
  414. X    page
  415. X
  416. X     This variable determines what kind of paging is used for LIST,
  417. X     TYPE, and HEADER commands.  If the variable does not exist, paging
  418. X     is turned off.  If set to null (no string), an internal paging
  419. X     routine is used.  If set to a value, an internal paging routine is
  420. X     used using the value as the page length.  the 'page' variable can
  421. X     also be set to a command, such as 'more' or 'page', in which case,
  422. X     the output is piped through those commands:
  423. X
  424. X     set page        Turn paging on (internal page routine)
  425. X     set page 25        Internal page routine... 25 rows/screen
  426. X     set page more        Use 'more' command to pipe output through
  427. X     set page page        Use 'page' command to pipe output through
  428. X
  429. X     you could also conceviably say:  'set page cat > x', or
  430. X     'set page cat | lpr', but be very careful.
  431. X
  432. X    sendmail
  433. X
  434. X     This variable will redirect DMAIL as to where the mailer program
  435. X     is.  The mailer program must be compatible with /usr/lib/sendmail
  436. X     which is the default used if the 'sendmail' variable isn't set
  437. X     to anything:
  438. X
  439. X     set sendmail bin/mysendmail
  440. X
  441. X    vibreak
  442. X
  443. X     This variable, when set, allows the INTR character to abort a
  444. X     reply, mail, or forward command.  Otherwise, if this variable is
  445. X     not present, INTR will not abort the above commands.
  446. X
  447. X    verbose
  448. X
  449. X     This variable, when set, causes the -v flag to be sent to
  450. X     sendmail.  In addition, DMAIL will wait for sendmail to complete
  451. X     before returning your prompt.
  452. X
  453. X    comlinemail
  454. X
  455. X     This variable is set when dmail is invoked with a command line
  456. X     user list (e.g.  dmail charlie mary mark). Usually, one uses
  457. X     this variable in an IF construct.  A good example would be that
  458. X     you may usually CD to a mail directory, but you don't want to
  459. X     CD when dmail is run with a command line user-list:
  460. X
  461. X        if !comlinemail
  462. X            cd  ...
  463. X
  464. X     alternate definition: The comlinemail variable will NOT be set
  465. X     if dmail is in interactive mode.
  466. X
  467. X    header
  468. X
  469. X     The file specified by this variable will be appended onto the temp
  470. X     vi files in reply and mail.  The file is appended before you go into
  471. X     vi, so when you do, what you see is still what you get.
  472. X
  473. X    ask
  474. X
  475. X     If set, dmail will ask you what to to (quit, send, re-edit) after you
  476. X     leave the editor when sending mail.  If not set, the mail is sent as
  477. X     soon as you leave the editor (unless you didn't write anything).
  478. X
  479. X    archive
  480. X
  481. X     If set (to a file name), any mail you send out (mail/reply/etc...)
  482. X     will be archived to this file.  Usually, you provide a fully
  483. X     specified path so cd's won't effect the file location.
  484. X
  485. X    _headchar
  486. X
  487. X     This string is prepend to any included text when you do an upper-case
  488. X     reply (R) command.
  489. X
  490. X    replyfields
  491. X
  492. X     This string holds a list of fields which are searched for to
  493. X     determine which one to use in the To: field of your reply.  If
  494. X     this variable does not exist or none of the specified fields could
  495. X     be found, the 'From ' (not From:) mail header will be used.  The
  496. X     search ends at the first field found.    Example:
  497. X
  498. X     set replyfields "Reply-To: From:"
  499. X
  500. X.replyfields
  501. XSET replyfields "field1 field2 ..."
  502. X
  503. X     This string holds a list of fields which are searched for to
  504. X     determine which one to use in the To: field of your reply.  If
  505. X     this variable does not exist or none of the specified fields could
  506. X     be found, the 'From ' (not From:) mail header will be used.  The
  507. X     search ends at the first field found.    Example:
  508. X
  509. X     set replyfields "Reply-To: From:"
  510. X
  511. X.>
  512. XSET _HEADCHAR "string"
  513. X
  514. X    see SET.  The _headchar variable determines the string prepending all
  515. X    included text when you do an upper-case reply (R) command.
  516. X
  517. X.archive
  518. XSET ARCHIVE file
  519. X
  520. X    if the archive variable is set to a file path, any mail you send out
  521. X    will automatically be appended to that file.  Dmail pre-pends a
  522. X    "From ", so it is compatible with /bin/mail and so that you can
  523. X    dmail -f your archive file.  Additionaly, a "Date: " field is
  524. X    pre-pended so you know when you sent the message.  example:
  525. X
  526. X    set archive ~/Dmail/arch
  527. X
  528. X    since your .dmailrc is sourced even when you "dmail user .." from
  529. X    your csh, putting the above line in your .dmailrc will turn on
  530. X    archiving whenever you use dmail to send mail, command line or
  531. X    dmail prompt.
  532. X
  533. X    if unset or set to nothing, no archive is made.
  534. X
  535. X.ask
  536. XSET ASK
  537. X
  538. X    if the 'ask' variable is set (set ask), dmail will ask you what to do
  539. X    when you are finished editing mail rather than send it immediately.
  540. X    (see 'help set')
  541. X
  542. X.alias
  543. XALIAS [variable [string]]
  544. X
  545. X    Create an alias for a command.    With no arguments, ALIAS will display
  546. Xall active aliases.  With one argument, a particular alias is displayed (if
  547. Xit exists), or defined (if it did not previously exist).  With more than one
  548. Xargument, the particular alias is set to the string list specified.
  549. X
  550. Xalias
  551. Xalias hack "select From hacker , To hacker , Cc hacker"
  552. Xalias bye quit
  553. Xalias stuff "setlist 60 To ; list"
  554. X
  555. X    Usually, any arguments following the alias are appended to the
  556. Xexpansion.  However, you can place such arguments inside the alias somewhere
  557. Xby using the following construction:
  558. X
  559. Xalias myecho "%var echo $var ; list"
  560. X
  561. Xmyecho hello there  ---> echo hello there ; list
  562. X
  563. X    to unalias an alias, use the UNALIAS command.
  564. X
  565. X.unset
  566. X.unalias
  567. XUNSET var var var...
  568. XUNALIAS var var var...
  569. X
  570. X    Eradicate variables or aliases from memory.
  571. X
  572. X.setlist
  573. XSETLIST [-s] [columns] Field [columns] Field ...
  574. X
  575. X    -s prevents display of the list.
  576. XSet the list format used for LIST and TYPE.  The optional [columns]
  577. Xindicates how many columns to allocate for the Field specified.  The
  578. XField can be a partial match. However, case is observed:
  579. X
  580. Xsetlist 18 Fro    38 Sub    10 To  0 Dat
  581. X
  582. X18 columns for the From: field, etc... when TYPEing messages, the
  583. X[columns] is ignored, and each field is printed in its entirety.
  584. XNote that 0 columns have been allocated for the Date: field.
  585. XTherefore, the Date: field will not show up on the LIST command,
  586. Xbut will show up in the TYPE command.
  587. X
  588. X.cd
  589. XCD PATH
  590. X
  591. X    cd, as in csh.    Changes your base directory.  You can use
  592. X the shell escape '! pwd' to get your current working directory.
  593. X
  594. X.source
  595. XSOURCE file
  596. X
  597. X    Source a file.    The file is read in an executed in sequence.
  598. X
  599. X.preserve
  600. XPRE    <message list>
  601. X
  602. X    PRESERVE messages.  A message is MARKED if it has been read (has an 'r'
  603. Xflag from the LIST command).  Marked messages are moved from your readfile
  604. Xinto your outfile upon a QUIT.    If you are reading and writing to the same
  605. Xfile (i.e. from your mbox to your mbox), the 'r' flag has no effect.
  606. X
  607. X    However, if you are reading from your spool file, and want to keep
  608. Xread messages in your spool (that is, not move them to your mbox), you want
  609. Xto PRESERVE them.  This command simply unmarks them, so they appear not to
  610. Xhave been read.
  611. X
  612. X.mark
  613. XMARK <message list>
  614. X
  615. X    Mark messages specified as being already 'read'.  Remember that if
  616. Xyou executed DMAIL without a -f option, any message 'read' at the time
  617. Xyou quit will be moved to MBOX (or file specified by -o)
  618. X
  619. X.tag
  620. X.untag
  621. XTAG <list>
  622. XUNTAG <list>
  623. X
  624. X    The TAG command allow you to flag any message.    You can tag a set of
  625. Xmessages, then reference them all at once.  For instance, if you tag
  626. Xinteresting messages as you glance at them, you may then write them all
  627. Xto a file by 'write filename tag',  or list them with 'list tag'.
  628. XAlternately, you could delete all your taged messages with a single delete
  629. Xcommand 'delete tag'.  The 'tag' operand works in the same way as the 'all'
  630. Xoperand, except it works only on taged messages.
  631. X
  632. X    UNTAG will untag a particular message in your message list.  For
  633. Xinstance, to untag any taged messages in the entire message list, you would:
  634. X
  635. X select all
  636. X untag all    OR     untag tag
  637. X
  638. X    Note that 'untag all' and 'untag tag' have the same effect.
  639. X
  640. X.write
  641. XWRITE file <message list>
  642. X
  643. X    Write the given messages or the current message to a file.  The file
  644. Xfile is appended to.  Remember that you may specify 'all' to write
  645. Xall messages in the current select field to the file.  Messages will be
  646. Xmarked as having been writen, and will be deleted from the mail file
  647. Xwhen you 'quit'.  However, you may cause them to be kept in the mail
  648. Xfile by UNdeleting the messages (i.e.  undelete all)
  649. X
  650. X    You can also TAG the messages you want to write, and say
  651. X'write file tag' to write to the file all taged messages.
  652. X
  653. X.!
  654. X! [shell command]
  655. X
  656. X    Give yourself a shell or execute a shell command.  The shell forked
  657. Xis that specified by your SHELL enviroment variable, or /bin/sh if there is
  658. Xno SHELL enviroment variable.
  659. X
  660. X.x
  661. X.exit
  662. XX (EXIT)
  663. X
  664. X    EXIT out of DMAIL without changing any files.  Usually, one exits
  665. Xwith QUIT, which would cause deleted messages to disappear, and TYPEd
  666. Xmessages to go to MBOX (if you did not use the -f option with DMAIL).
  667. X
  668. X    If your outfile is the same as your infile, reading a message does
  669. Xnot effect anything.
  670. X
  671. X.quit
  672. XQUIT
  673. X
  674. X    Quit out of DMAIL. Delete any messages that were marked for deletion
  675. Xand if you executed DMAIL on /usr/spool/mail/ (default), any mail
  676. Xmarked 'read' will be placed in MBOX in your home directory
  677. X
  678. X.xswitch
  679. X.qswitch
  680. XXSWITCH fromfile [tofile]
  681. XQSWITCH fromfile [tofile]
  682. X
  683. X    Switch to a different set of files.  XSWITCH doesn't modify your
  684. Xold from and to files before switching, QSWITCH works as if you had QUIT
  685. Xstuff before switching to another set of files.
  686. X
  687. X    If no [tofile] is specified, the new tofile will be the same as the
  688. Xfromfile you specify.
  689. X
  690. X.help
  691. X.?
  692. XHELP [topic]
  693. X
  694. X    Give me help on a topic
  695. X
  696. X.dmail
  697. XCOMMAND LINE OPTIONS FOR DMAIL
  698. X
  699. X    dmail -O [-l rcfile] -f [file] -o [file] -F field -F field -F field ...
  700. X
  701. X    Default conditions:
  702. X        Home directory gotten from password entry
  703. X        User gotten from password entry
  704. X        Visual editor set to /usr/ucb/vi
  705. X
  706. X        VI BREAKOUT enabled
  707. X        READ file is /usr/spool/mail/$USER
  708. X        WRITE file is $HOME/mbox
  709. X        From:,    To:, and Subject: fields will be loaded into memory.
  710. X
  711. X    HOME    enviroment variable becomes home directory
  712. X    USER    enviroment variable becomes user name
  713. X    VISUAL    enviroment variable becomes editor used
  714. X
  715. X    -O            Go into interactive mode, even if there is no
  716. X                mail to read.
  717. X
  718. X    -f [from file]        Specify spool file to get mail from. If no file
  719. X                Argument is given, $HOME/MBOX is used.
  720. X
  721. X    -o [to file]        Specify file to write to, If no Argument
  722. X                is given, $HOME/.MBOX is used.    Note that
  723. X                the default without -o is $HOME/MBOX
  724. X
  725. X    -f -o            With no file arguments causes both READ and
  726. X                WRITE files to be $HOME/.MBOX
  727. X
  728. X    -F field        Append this field to those which will be
  729. X                used on initial load.  If, During usage of the
  730. X                program you specify a field which is not in
  731. X                memory, DMAIL will be forced to re-load the
  732. X                entire spool file, which can take a long time
  733. X                if you have more than 64K in the file
  734. X
  735. X    -l rcfile        Use this as the rc file rather than .dmailrc
  736. X
  737. X    -L            Do not source the rc file on boot
  738. X
  739. X
  740. END_OF_FILE
  741. if test 23728 -ne `wc -c <'uucp2/src/dmail/dmail.help'`; then
  742.     echo shar: \"'uucp2/src/dmail/dmail.help'\" unpacked with wrong size!
  743. fi
  744. # end of 'uucp2/src/dmail/dmail.help'
  745. fi
  746. if test -f 'uucp2/src/news/rnews.c' -a "${1}" != "-c" ; then 
  747.   echo shar: Will not clobber existing file \"'uucp2/src/news/rnews.c'\"
  748. else
  749. echo shar: Extracting \"'uucp2/src/news/rnews.c'\" \(21274 characters\)
  750. sed "s/^X//" >'uucp2/src/news/rnews.c' <<'END_OF_FILE'
  751. X
  752. X/*
  753. X *  RNEWS.C
  754. X *
  755. X *  Copyright 1988 by William Loftus.  All rights reserved.
  756. X *  Extensive Changes Copyright 1990 by Matthew Dillon, All Rights Reserved
  757. X *
  758. X *  This is rnews for compressed news.    News 2.11 will uux
  759. X *  a file to this system that will be in compressed format.
  760. X *  This program will strip off the "#! cunbatch", uncompress
  761. X *  the news, and call unbatch.  If the news is not in compressed
  762. X *  format it will just pass it to unbatch.
  763. X *
  764. X *  Each newsgroup directory has a .next file which indicates the next
  765. X *  article number to write.  This number rolls over at 32767.
  766. X */
  767. X
  768. X#include "news.h"
  769. X#include <errno.h>
  770. X#include <ctype.h>
  771. X#include <sys/stat.h>        /* outrageous place for the mkdir() proto! */
  772. X#include <log.h>
  773. X
  774. Xextern char *TmpFileName();
  775. X
  776. XIDENT(".04");
  777. X
  778. Xstatic int dofile(void);
  779. Xstatic void unbatch(char *);
  780. Xstatic long store_art(long size, char *);
  781. Xstatic void uncompress_news(void);
  782. Xstatic void news_exit(int stat);
  783. X
  784. X#define exit news_exit
  785. X
  786. Xstatic char TmpBuf[2048];
  787. Xchar homedir[256];
  788. X
  789. Xchar *NewsDir;
  790. Xchar *WKName;
  791. X
  792. Xvoid copy_uualtspool();
  793. X
  794. X#define PROG_NAME "RNews"
  795. X
  796. Xint
  797. Xmain(ac, av)
  798. Xint ac;
  799. Xchar *av[];
  800. X{
  801. X    int ret = 0;
  802. X    short i;
  803. X
  804. X    LogProgram = PROG_NAME;
  805. X    fclose(stderr);         /* Assume we are running in the background */
  806. X
  807. X    getcwd(homedir, sizeof(homedir));
  808. X    NewsDir = GetConfigDir(UUNEWS);
  809. X
  810. X    if (chdir(NewsDir) != 0) {
  811. X    ulog(0, "NewsDir %s doesn't exist; quitting", NewsDir);
  812. X    exit(1);
  813. X    }
  814. X    WKName = strdup(TmpFileName("news-work"));
  815. X
  816. X    for (i = 1; i < ac; ++i) {
  817. X    char *ptr = av[i];
  818. X    if (*ptr != '=')
  819. X        break;
  820. X    switch(ptr[1]) {
  821. X    case 'x':
  822. X        LogLevel = atoi(ptr + 2);
  823. X        break;
  824. X    default:
  825. X        printf("unknown flag '%s' ignored\n", ptr + 1);
  826. X        break;
  827. X    }
  828. X    }
  829. X    if (i < ac && strcmp(av[i], "UseNet") == 0) {
  830. X    ulog(1, "Starting standard input");
  831. X    if (atoi(GetConfig(RNEWSDEBUG, "0"))) {
  832. X        ulog(-1, "RNewsDebug, copying to UUAltSpool:");
  833. X        copy_uualtspool();
  834. X    }
  835. X
  836. X    if (dofile() < 0)
  837. X        ret = 1;
  838. X    } else {
  839. X    for (; i < ac; ++i) {
  840. X        char *ptr = av[i];
  841. X
  842. X        chdir(homedir);         /* so relative file names will work */
  843. X        ulog(1, "Starting file %s", ptr);
  844. X        if (freopen(ptr, "r", stdin) == NULL) {
  845. X        ulog(0, "Cannot open news file %s", ptr);
  846. X        continue;
  847. X        }
  848. X        chdir(NewsDir);
  849. X        if (dofile() < 0)
  850. X        ret = 1;
  851. X    }
  852. X    }
  853. X    if (ret == 0)
  854. X    remove(WKName);
  855. X    exit(ret);
  856. X}
  857. X
  858. Xstatic int
  859. Xdofile(void)
  860. X{
  861. X    char buf[64];
  862. X
  863. X    if (fgets(buf, sizeof(buf), stdin)) {
  864. X    if (strncmp(buf, "#! cunbatch", 11) == 0) {
  865. X        uncompress_news();
  866. X    } else {
  867. X        unbatch(buf);
  868. X    }
  869. X    }
  870. X    fclose(stdin);
  871. X    return(0);
  872. X}
  873. X
  874. X/*
  875. X * Unbatch, an Amiga unbatcher.
  876. X *
  877. X *    Written by Fred Cassirer, 10/8/88.
  878. X *    Some unbatch code originally taken from News2.11 sources.
  879. X *
  880. X *    Ported to Lattice 5.0
  881. X *    Added config.h file
  882. X *    Added use of ERRORFILE
  883. X *    11/23/1988  Dan 'Sneakers' Schein
  884. X *
  885. X * This code (as well as the unbatch stuff) is free for anyone who thinks
  886. X * they can get some use out of it.
  887. X *
  888. X *    Articles will only be placed in newsgroups as defined in the
  889. X *    "LIB/NewsGroups" control file.  Articles which are not listed
  890. X *    in the control file are placed in the "junk" directory.  Articles
  891. X *    are sequenced by the sequencer in "LIB/seqnews". This could
  892. X *    possibly be updated to use a sequencer within each of the news
  893. X *    subdirectories, to more closely resemble the News system under Unix.
  894. X *
  895. X *    (sequence numbers are not kept in the NewsGroups file itself but in
  896. X *    each news directory.  This protects against accidents)
  897. X *
  898. X *    The NewsGroups file contains one newsgroup per line, plus an optional
  899. X *    # days expiration.  For example:
  900. X *
  901. X *        comp.sys.amiga  30
  902. X *
  903. X *    Unbatch will also take command line args of files to be unbatched.
  904. X *    Files on the command line are not removed, they should be removed
  905. X *    after running unbatch.
  906. X */
  907. X
  908. Xstatic struct group {
  909. X    struct group *next;
  910. X    char name[1];
  911. X} groups;
  912. X
  913. Xstatic void
  914. Xinitgroups(void)
  915. X{
  916. X    struct group *gp;
  917. X    long len;
  918. X    FILE *fp;
  919. X    char buf[50];
  920. X
  921. X    if (groups.next != NULL)
  922. X    return;
  923. X
  924. X    if ((fp = openlib("newsgroups")) == NULL) {
  925. X    ulog(0, "Couldn't open LIB/newsgroups file");
  926. X    exit(2);
  927. X    }
  928. X
  929. X    gp = &groups;
  930. X    while (fgets(buf, sizeof(buf), fp)) {
  931. X    short c;
  932. X    for (len = 0; (c = buf[len]) != ' ' && c != 9 && c != '\n'; ++len);
  933. X    buf[len] = 0;
  934. X    if ((gp->next = (struct group *)malloc(4+len+1)) == NULL) {
  935. X        ulog(0, "Malloc failed!");
  936. X        exit(4);
  937. X    }
  938. X    gp = gp->next;
  939. X    strcpy(gp->name, buf);
  940. X    }
  941. X    gp->next = NULL;
  942. X    fclose(fp);
  943. X}
  944. X
  945. Xstatic char *
  946. Xfinddir(dir)
  947. Xchar *dir;
  948. X{
  949. X    struct group *gp, *dp = NULL;
  950. X    char *p;
  951. X    int c;
  952. X
  953. X    do {
  954. X    p = dir;
  955. X    do {
  956. X        c = *++dir;
  957. X    } while (c != ' ' && c != ',' && c != '\n' && c != '\0');
  958. X    *dir++ = '\0';
  959. X
  960. X    for (gp = groups.next; gp != NULL; gp = gp->next) {
  961. X        if (gp == dp)
  962. X        break;
  963. X        if (strcmp(gp->name, p) == 0) {
  964. X        dp = gp;
  965. X        break;
  966. X        }
  967. X    }
  968. X    } while (c != '\n' && c != '\0');
  969. X
  970. X    if (dp)
  971. X    return (dp->name);
  972. X    return ("junk");        /* Oops, not a known newsgroup */
  973. X}
  974. X
  975. X/*
  976. X * unbatchnews: extract news in batched format and process it one article
  977. X * at a time.  The format looks like
  978. X *    #! rnews 1234
  979. X *    article containing 1234 characters
  980. X *    #! rnews 4321
  981. X *    article containing 4321 characters
  982. X */
  983. X
  984. Xstatic void
  985. Xunbatch(hdr)
  986. Xchar *hdr;
  987. X{
  988. X    long size;
  989. X    char buf[64];
  990. X
  991. X    if (hdr) {
  992. X    strcpy(buf, hdr);
  993. X    } else {
  994. X    buf[0] = 0;
  995. X    fgets(buf, sizeof(buf), stdin);
  996. X    }
  997. X    if (strncmp(buf, "#! rnews ", 9) != 0) {
  998. X    store_art(10000000L, buf);
  999. X    return;
  1000. X    }
  1001. X    do {
  1002. X    /* second strcmp is kludge for bug */
  1003. X
  1004. X    if (strncmp(buf, "#! rnews ", 9) != 0 && strncmp(buf, "! rnews ", 8) != 0) {
  1005. X        char *cp;
  1006. X
  1007. X        for (cp = buf; *cp; ++cp) {
  1008. X        if (!isprint(*cp) && !isspace(*cp))
  1009. X            *cp = '?';
  1010. X        }
  1011. X        *--cp = '\0';
  1012. X        ulog(0, "out of sync, skipping <%s>", buf);
  1013. X        continue;
  1014. X    }
  1015. X
  1016. X    size = atol(buf + 8 + (buf[0] == '#'));
  1017. X    if (size <= 0) {
  1018. X        ulog(0, "nonsense size %ld", size);
  1019. X        continue;
  1020. X    }
  1021. X
  1022. X    if (store_art(size, NULL) > 0) {
  1023. X        /*
  1024. X         * If we got a truncated batch, don't process the
  1025. X         * last article; it will probably be received again.
  1026. X         */
  1027. X        ulog(0, "truncated batch");
  1028. X        break;
  1029. X    }
  1030. X    } while (fgets(buf, sizeof(buf), stdin));
  1031. X}
  1032. X
  1033. Xstatic long
  1034. Xstore_art(size, ibuf)
  1035. Xlong size;
  1036. Xchar *ibuf;
  1037. X{
  1038. X    int c;
  1039. X    FILE *pfn;
  1040. X    FILE *seq;
  1041. X    unsigned long seqno;
  1042. X    char *dir;
  1043. X
  1044. X    initgroups();
  1045. X
  1046. X    ulog(2, "SIZE %ld", size);
  1047. X
  1048. X    if ((pfn = fopen("ArticleTemp", "w")) == NULL) {
  1049. X    ulog(0, "Could not creat article temp file");
  1050. X    exit(3);
  1051. X    }
  1052. X
  1053. X    dir = "Rejects";
  1054. X
  1055. X    if (ibuf)
  1056. X    fputs(ibuf, pfn);
  1057. X
  1058. X    /*
  1059. X     *    search for Newsgroups: line in a manner independant of the line
  1060. X     *    length, which can be anything.
  1061. X     */
  1062. X
  1063. X    {
  1064. X    int i = 0;
  1065. X
  1066. X    while (size && (c = getc(stdin)) != EOF) {
  1067. X        putc(c, pfn);
  1068. X        --size;
  1069. X        TmpBuf[i++] = c;
  1070. X        if (i == sizeof(TmpBuf))    /*  very long non-NewsGroups: header  */
  1071. X        i = 0;
  1072. X        if (c == '\n')
  1073. X        i = 0;
  1074. X        if (c == ':') {
  1075. X        if (strncmp(TmpBuf, "Newsgroups:", 11) == 0) {
  1076. X            if (fgets(TmpBuf, sizeof(TmpBuf), stdin)) {
  1077. X            fputs(TmpBuf, pfn);
  1078. X            size -= strlen(TmpBuf);
  1079. X            for (i = 0; TmpBuf[i] == ' ' || TmpBuf[i] == 9; ++i);
  1080. X            dir = finddir(TmpBuf + i);
  1081. X            break;
  1082. X            }
  1083. X        }
  1084. X        }
  1085. X    }
  1086. X    }
  1087. X    while (size > 0) {
  1088. X    int n = (size > sizeof(TmpBuf)) ? sizeof(TmpBuf) : size;
  1089. X    int r = fread(TmpBuf, 1, n, stdin);
  1090. X
  1091. X    if (r <= 0)
  1092. X        break;
  1093. X    fwrite(TmpBuf, 1, r, pfn);
  1094. X    size -= r;
  1095. X    }
  1096. X    fflush(pfn);
  1097. X    if (ferror(pfn)) {              /* disk full? */
  1098. X    fclose(pfn);
  1099. X    remove("ArticleTemp");
  1100. X    ulog(0, "error writing temporary file");
  1101. X    return (-1);
  1102. X    }
  1103. X    fclose(pfn);
  1104. X
  1105. X    sprintf(TmpBuf, "%s/.next", dir);
  1106. X    if (IsDir(dir)) {
  1107. X    if ((seq = fopen(TmpBuf, "r")) == NULL) {
  1108. X        ulog(0, "sequencer file '%s' not found, will create", TmpBuf);
  1109. X        seqno = 1000;
  1110. X    } else {
  1111. X        fscanf(seq, "%ld", &seqno);
  1112. X        fclose(seq);
  1113. X    }
  1114. X    } else if (mkdir(dir) != 0) {
  1115. X    ulog(0, "Cannot create directory for '%s'; article dropped", dir);
  1116. X    return (-1);
  1117. X    } else {
  1118. X    seqno = 1;
  1119. X    }
  1120. X    if ((seq = fopen(TmpBuf, "w")) == NULL) {
  1121. X    ulog(0, "Couldn't create sequencer for '%s'; article dropped", dir);
  1122. X    return (-1);
  1123. X    } else {
  1124. X    fprintf(seq, "%ld\n", (seqno + 1) & 0x7FFF);
  1125. X    fclose(seq);
  1126. X    }
  1127. X
  1128. X    sprintf(TmpBuf, "%s/%ld", dir, seqno);
  1129. X    ulog(2, "FILE %s", TmpBuf);
  1130. X    if (rename("ArticleTemp", TmpBuf) != 0) {
  1131. X    remove("ArticleTemp");
  1132. X    ulog(0, "Could not rename article to %s", TmpBuf);
  1133. X    }
  1134. X    return (size);
  1135. X}
  1136. X
  1137. X/*
  1138. X * Set USERMEM to the maximum amount of physical user memory available
  1139. X * in bytes.  USERMEM is used to determine the maximum BITS that can be used
  1140. X * for compression.
  1141. X *
  1142. X * SACREDMEM is the amount of physical memory saved for others; compress
  1143. X * will hog the rest.
  1144. X */
  1145. X
  1146. X#ifndef SACREDMEM
  1147. X#define SACREDMEM    0
  1148. X#endif
  1149. X
  1150. X#ifndef USERMEM
  1151. X#  define USERMEM    450000    /* default user memory */
  1152. X#endif
  1153. X
  1154. X#ifdef AMIGA            /* Commodore Amiga */
  1155. X# define BITS        16
  1156. X# define M_XENIX    /* so we can use small model (faster) */
  1157. X# undef USERMEM
  1158. X#endif
  1159. X
  1160. X#ifdef interdata        /* (Perkin-Elmer) */
  1161. X#define SIGNED_COMPARE_SLOW    /* signed compare is slower than unsigned */
  1162. X#endif
  1163. X
  1164. X#ifdef pdp11
  1165. X# define BITS    12    /* max bits/code for 16-bit machine */
  1166. X# define NO_UCHAR    /* also if "unsigned char" functions as signed char */
  1167. X# undef USERMEM
  1168. X#endif /* pdp11 */    /* don't forget to compile with -i */
  1169. X
  1170. X#ifdef z8000
  1171. X# define BITS    12
  1172. X# undef vax        /* weird preprocessor */
  1173. X# undef USERMEM
  1174. X#endif /* z8000 */
  1175. X
  1176. X#ifdef pcxt
  1177. X# define BITS    12
  1178. X# undef USERMEM
  1179. X#endif /* pcxt */
  1180. X
  1181. X#ifdef USERMEM
  1182. X# if USERMEM >= (433484+SACREDMEM)
  1183. X#  define PBITS 16
  1184. X# else
  1185. X#  if USERMEM >= (229600+SACREDMEM)
  1186. X#   define PBITS    15
  1187. X#  else
  1188. X#   if USERMEM >= (127536+SACREDMEM)
  1189. X#    define PBITS    14
  1190. X#   else
  1191. X#    if USERMEM >= (73464+SACREDMEM)
  1192. X#     define PBITS    13
  1193. X#    else
  1194. X#     define PBITS    12
  1195. X#    endif
  1196. X#   endif
  1197. X#  endif
  1198. X# endif
  1199. X# undef USERMEM
  1200. X#endif /* USERMEM */
  1201. X
  1202. X#ifdef PBITS        /* Preferred BITS for this memory size */
  1203. X# ifndef BITS
  1204. X#  define BITS PBITS
  1205. X# endif BITS
  1206. X#endif /* PBITS */
  1207. X
  1208. X#if BITS == 16
  1209. X# define HSIZE    69001        /* 95% occupancy */
  1210. X#endif
  1211. X#if BITS == 15
  1212. X# define HSIZE    35023        /* 94% occupancy */
  1213. X#endif
  1214. X#if BITS == 14
  1215. X# define HSIZE    18013        /* 91% occupancy */
  1216. X#endif
  1217. X#if BITS == 13
  1218. X# define HSIZE    9001        /* 91% occupancy */
  1219. X#endif
  1220. X#if BITS <= 12
  1221. X# define HSIZE    5003        /* 80% occupancy */
  1222. X#endif
  1223. X
  1224. X#ifdef M_XENIX            /* Stupid compiler can't handle arrays with */
  1225. X# if BITS == 16         /* more than 65535 bytes - so we fake it */
  1226. X#  define XENIX_16
  1227. X# else
  1228. X#  if BITS > 13         /* Code only handles BITS = 12, 13, or 16 */
  1229. X#   define BITS 13
  1230. X#  endif
  1231. X# endif
  1232. X#endif
  1233. X
  1234. X/*
  1235. X * a code_int must be able to hold 2**BITS values of type int, and also -1
  1236. X */
  1237. X#if BITS > 15
  1238. Xtypedef long int    code_int;
  1239. X#else
  1240. Xtypedef int        code_int;
  1241. X#endif
  1242. X
  1243. X#ifdef SIGNED_COMPARE_SLOW
  1244. Xtypedef unsigned long int count_int;
  1245. X#else
  1246. Xtypedef long int    count_int;
  1247. X#endif
  1248. X
  1249. X#ifdef NO_UCHAR
  1250. Xtypedef char        char_type;
  1251. X#else
  1252. Xtypedef unsigned char    char_type;
  1253. X#endif /* UCHAR */
  1254. Xchar_type magic_header[] = { "\037\235" };      /* 1F 9D */
  1255. X
  1256. X/* Defines for third byte of header */
  1257. X#define BIT_MASK    0x1f
  1258. X#define BLOCK_MASK    0x80
  1259. X/* Masks 0x40 and 0x20 are free.  I think 0x20 should mean that there is
  1260. X   a fourth header byte (for expansion).
  1261. X*/
  1262. X#define INIT_BITS    9    /* initial number of bits/code */
  1263. X
  1264. Xint n_bits;            /* number of bits/code */
  1265. Xint maxbits = BITS;        /* user settable max # bits/code */
  1266. Xcode_int maxcode;        /* maximum code, given n_bits */
  1267. Xcode_int maxmaxcode;    /* 1 << BITS */ /* should NEVER generate this code */
  1268. X#define MAXCODE(n_bits)         ((((code_int)1) << (n_bits)) - 1)
  1269. X
  1270. X#ifdef XENIX_16
  1271. Xcount_int * htab[9] = { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL };
  1272. Xunsigned short * codetab[5] = { NULL, NULL, NULL, NULL, NULL };
  1273. X#else    /* Normal machine */
  1274. Xcount_int    htab[HSIZE];
  1275. Xunsigned short    codetab[HSIZE];
  1276. X#endif /* XENIX_16 */
  1277. Xcode_int hsize = HSIZE;     /* for dynamic table sizing */
  1278. X
  1279. X/*
  1280. X * The tab_suffix table needs 2**BITS characters.  We get this from the
  1281. X * beginning of htab.  The output stack uses the rest of htab, and contains
  1282. X * characters.    There is plenty of room for any possible stack (stack used
  1283. X * to be 8000 characters).
  1284. X */
  1285. X
  1286. X#ifdef XENIX_16
  1287. X# define tab_prefixof(i)        (codetab[(i)>>14][(i) & 0x3FFF])
  1288. X# define tab_suffixof(i)        ((char_type *)htab[(i)>>15])[(i) & 0x7FFF]
  1289. X# define de_stack        ((char_type *)(htab[2]))
  1290. X#else    /* Normal machine */
  1291. X# define tab_prefixof(i)        codetab[i]
  1292. X# define tab_suffixof(i)        (((char_type *)htab)[i])
  1293. X/* FIXME??? This next line is suspect..... */
  1294. X# define de_stack        ((char_type *)(((long)htab)+(((code_int)1)<<BITS)))
  1295. X#endif /* XENIX_16 */
  1296. X
  1297. Xcode_int free_ent = 0;    /* first unused entry */
  1298. X
  1299. Xstatic code_int getcode(void);
  1300. Xstatic void writeerr(void);
  1301. X
  1302. X/*
  1303. X * block compression parameters -- after all codes are used up,
  1304. X * and compression rate changes, start over.
  1305. X */
  1306. Xint block_compress = BLOCK_MASK;
  1307. Xint clear_flg = 0;
  1308. X
  1309. X/*
  1310. X * the next two codes should not be changed lightly, as they must not
  1311. X * lie within the contiguous general code space.
  1312. X */
  1313. X#define FIRST    257    /* first free entry */
  1314. X#define CLEAR    256    /* table clear output code */
  1315. X
  1316. X/*
  1317. X * Decompress stdin to stdout.    This routine adapts to the codes in the
  1318. X * file building the "string" table on-the-fly, requiring no table to
  1319. X * be stored in the compressed file.
  1320. X */
  1321. X
  1322. X#ifdef XENIX_16
  1323. X
  1324. Xstatic void *
  1325. Xsafealloc(long size)
  1326. X{
  1327. X    int retry = 30;
  1328. X    void *p;
  1329. X
  1330. X    while ((p = malloc(size)) == NULL) {
  1331. X    if (--retry < 0) {
  1332. X        ulog(0, "Can't get memory to decompress news batch -- terminating");
  1333. X        exit(20);
  1334. X    }
  1335. X    ulog(0, "Can't get memory to decompress news batch -- will retry");
  1336. X    sleep(30);
  1337. X    }
  1338. X    return p;
  1339. X}
  1340. X
  1341. X#endif /* XENIX_16 */
  1342. X
  1343. Xstatic void
  1344. Xdecompress(void)
  1345. X{
  1346. X    register char_type *stackp;
  1347. X    register int finchar;
  1348. X    register code_int code, oldcode, incode;
  1349. X
  1350. X    maxcode = MAXCODE(n_bits = INIT_BITS);
  1351. X    free_ent = ((block_compress) ? FIRST : 256);
  1352. X    finchar = oldcode = getcode();
  1353. X    if(oldcode == -1)       /* EOF already? */
  1354. X        return;     /* Get out of here */
  1355. X
  1356. X#ifdef XENIX_16
  1357. X    htab[0] = (code_int *)safealloc(8192*sizeof(code_int));
  1358. X    htab[1] = (code_int *)safealloc(8192*sizeof(code_int));
  1359. X    htab[2] = (code_int *)safealloc(8192*sizeof(char));
  1360. X    for (code = 0; code < 5; ++code)
  1361. X        codetab[code] = (unsigned short *)
  1362. X                safealloc(16384*sizeof(unsigned short));
  1363. X#endif /* XENIX_16 */
  1364. X
  1365. X    /*
  1366. X     * As above, initialize the first 256 entries in the table.
  1367. X     */
  1368. X    for (code = 255; code >= 0; code--) {
  1369. X        tab_prefixof(code) = 0;
  1370. X        tab_suffixof(code) = (char_type)code;
  1371. X    }
  1372. X
  1373. X    putchar((char)finchar); /* first code must be 8 bits = char */
  1374. X    if(ferror(stdout))      /* Crash if can't write */
  1375. X        writeerr();
  1376. X    stackp = de_stack;
  1377. X
  1378. X    while ((code = getcode()) > -1) {
  1379. X        if ((code == CLEAR) && block_compress) {
  1380. X            for (code = 255; code >= 0; code--)
  1381. X                tab_prefixof(code) = 0;
  1382. X            clear_flg = 1;
  1383. X            free_ent = FIRST - 1;
  1384. X            if ((code = getcode()) == -1)   /* O, untimely death! */
  1385. X                break;
  1386. X        }
  1387. X        incode = code;
  1388. X        /*
  1389. X         * Special case for KwKwK string.
  1390. X         */
  1391. X        if (code >= free_ent) {
  1392. X            *stackp++ = finchar;
  1393. X            code = oldcode;
  1394. X        }
  1395. X
  1396. X        /*
  1397. X         * Generate output characters in reverse order
  1398. X         */
  1399. X#ifdef SIGNED_COMPARE_SLOW
  1400. X        while (((unsigned long)code) >= ((unsigned long)256))
  1401. X#else
  1402. X        while (code >= 256)
  1403. X#endif
  1404. X        {
  1405. X            *stackp++ = tab_suffixof(code);
  1406. X            code = tab_prefixof(code);
  1407. X        }
  1408. X        *stackp++ = finchar = tab_suffixof(code);
  1409. X
  1410. X        /*
  1411. X         * And put them out in forward order
  1412. X         */
  1413. X        do {    register int c = *--stackp;
  1414. X            putc(c, stdout);        /* putc is often a macro! */
  1415. X        } while (stackp > de_stack);
  1416. X
  1417. X        /*
  1418. X         * Generate the new entry.
  1419. X         */
  1420. X        if ((code=free_ent) < maxmaxcode) {
  1421. X            tab_prefixof(code) = (unsigned short)oldcode;
  1422. X            tab_suffixof(code) = finchar;
  1423. X            free_ent = code+1;
  1424. X        }
  1425. X        /*
  1426. X         * Remember previous code.
  1427. X         */
  1428. X        oldcode = incode;
  1429. X    }
  1430. X
  1431. X    fflush(stdout);
  1432. X    if(ferror(stdout))
  1433. X        writeerr();
  1434. X
  1435. X#ifdef XENIX_16
  1436. X    free(htab[0]), htab[0] = NULL;
  1437. X    free(htab[1]), htab[1] = NULL;
  1438. X    free(htab[2]), htab[2] = NULL;
  1439. X    for (code = 0; code < 5; ++code)
  1440. X        free(codetab[code]), codetab[code] = NULL;
  1441. X#endif /* XENIX_16 */
  1442. X}
  1443. X
  1444. X/*****************************************************************
  1445. X * TAG(getcode)
  1446. X *
  1447. X * Read one code from the standard input.  If EOF, return -1.
  1448. X * Inputs:
  1449. X *    stdin
  1450. X * Outputs:
  1451. X *    code or -1 is returned.
  1452. X */
  1453. X
  1454. X#ifndef vax
  1455. Xchar_type rmask[9] = {0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
  1456. X#endif /* vax */
  1457. X
  1458. Xstatic code_int
  1459. Xgetcode(void)
  1460. X{
  1461. X    /*
  1462. X     * On the VAX, it is important to have the register declarations
  1463. X     * in exactly the order given, or the asm will break.
  1464. X     */
  1465. X    register code_int code;
  1466. X    static int offset = 0, size = 0;
  1467. X    static char_type buf[BITS];
  1468. X    register int r_off, bits;
  1469. X    register char_type *bp = buf;
  1470. X
  1471. X    if (clear_flg > 0 || offset >= size || free_ent > maxcode) {
  1472. X        /*
  1473. X         * If the next entry will be too big for the current code
  1474. X         * size, then we must increase the size.  This implies reading
  1475. X         * a new buffer full, too.
  1476. X         */
  1477. X        if (free_ent > maxcode) {
  1478. X            n_bits++;
  1479. X            if (n_bits == maxbits)
  1480. X                /* won't get any bigger now */
  1481. X                maxcode = maxmaxcode;
  1482. X            else
  1483. X                maxcode = MAXCODE(n_bits);
  1484. X        }
  1485. X        if (clear_flg > 0) {
  1486. X            maxcode = MAXCODE(n_bits = INIT_BITS);
  1487. X            clear_flg = 0;
  1488. X        }
  1489. X        size = fread(buf, 1, n_bits, stdin);
  1490. X        if (size <= 0)
  1491. X            return -1;    /* end of file */
  1492. X        offset = 0;
  1493. X        /* Round size down to integral number of codes */
  1494. X        size = (size << 3) - (n_bits - 1);
  1495. X    }
  1496. X    r_off = offset;
  1497. X    bits = n_bits;
  1498. X#ifdef vax
  1499. X    asm("extzv      r10,r9,(r8),r11");
  1500. X#else /* not a vax */
  1501. X    /*
  1502. X     * Get to the first byte.
  1503. X     */
  1504. X    bp += (r_off >> 3);
  1505. X    r_off &= 7;
  1506. X    /* Get first part (low order bits) */
  1507. X#ifdef NO_UCHAR
  1508. X    code = ((*bp++ >> r_off) & rmask[8 - r_off]) & 0xff;
  1509. X#else
  1510. X    code = (*bp++ >> r_off);
  1511. X#endif /* NO_UCHAR */
  1512. X    bits -= (8 - r_off);
  1513. X    r_off = 8 - r_off;    /* now, offset into code word */
  1514. X    /* Get any 8 bit parts in the middle (<=1 for up to 16 bits). */
  1515. X    if (bits >= 8) {
  1516. X#ifdef NO_UCHAR
  1517. X        code |= (*bp++ & 0xff) << r_off;
  1518. X#else
  1519. X        code |= *bp++ << r_off;
  1520. X#endif /* NO_UCHAR */
  1521. X        r_off += 8;
  1522. X        bits -= 8;
  1523. X    }
  1524. X    /* high order bits. */
  1525. X    code |= (*bp & rmask[bits]) << r_off;
  1526. X#endif /* vax */
  1527. X    offset += n_bits;
  1528. X
  1529. X    return code;
  1530. X}
  1531. X
  1532. X#ifdef DEBUG
  1533. X
  1534. Xstatic void _fprintf(FILE *fi, const char *ctl, ...) { }
  1535. X
  1536. Xstatic /*volatile*/ void
  1537. Xprintcodes(void)
  1538. X{
  1539. X    /*
  1540. X     * Just print out codes from input file.  For debugging.
  1541. X     */
  1542. X    code_int code;
  1543. X    int col = 0, bits;
  1544. X
  1545. X    bits = n_bits = INIT_BITS;
  1546. X    maxcode = MAXCODE(n_bits);
  1547. X    free_ent = ((block_compress) ? FIRST : 256);
  1548. X    while ((code = getcode()) >= 0) {
  1549. X        if ((code == CLEAR) && block_compress) {
  1550. X            free_ent = FIRST - 1;
  1551. X            clear_flg = 1;
  1552. X        } else if (free_ent < maxmaxcode)
  1553. X            free_ent++;
  1554. X        if (bits != n_bits) {
  1555. X            _fprintf(stderr, "\nChange to %d bits\n", n_bits);
  1556. X            bits = n_bits;
  1557. X            col = 0;
  1558. X        }
  1559. X        _fprintf(stderr, "%5d%c", code,
  1560. X            (col+=6) >= 74 ? (col = 0, '\n') : ' ');
  1561. X    }
  1562. X    _fprintf(stderr, "\n");
  1563. X    exit(0);
  1564. X}
  1565. X
  1566. Xstatic int
  1567. Xin_stack(register int c, register int stack_top)
  1568. X{
  1569. X    if ((isprint(c) && c != '\\') || c == ' ') {
  1570. X        de_stack[--stack_top] = c;
  1571. X    } else {
  1572. X        switch(c) {
  1573. X        case '\n': de_stack[--stack_top] = 'n'; break;
  1574. X        case '\t': de_stack[--stack_top] = 't'; break;
  1575. X        case '\b': de_stack[--stack_top] = 'b'; break;
  1576. X        case '\f': de_stack[--stack_top] = 'f'; break;
  1577. X        case '\r': de_stack[--stack_top] = 'r'; break;
  1578. X        case '\\': de_stack[--stack_top] = '\\'; break;
  1579. X        default:
  1580. X            de_stack[--stack_top] = '0' + c % 8;
  1581. X            de_stack[--stack_top] = '0' + (c / 8) % 8;
  1582. X            de_stack[--stack_top] = '0' + c / 64;
  1583. X            break;
  1584. X        }
  1585. X        de_stack[--stack_top] = '\\';
  1586. X    }
  1587. X    return stack_top;
  1588. X}
  1589. X#endif /* DEBUG */
  1590. X
  1591. Xstatic void
  1592. Xwriteerr(void)
  1593. X{
  1594. X    ulog(0, "Error while writing to '%s'", WKName);
  1595. X    remove(WKName);
  1596. X    exit(1);
  1597. X}
  1598. X
  1599. Xstatic void
  1600. Xuncompress_news(void)
  1601. X{
  1602. X    if (freopen(WKName, "w", stdout) == NULL) {
  1603. X    ulog(0, "Can't open uncompressed file for output");
  1604. X    return;
  1605. X    }
  1606. X
  1607. X    /* Check the magic number */
  1608. X
  1609. X    if ((getc(stdin)!=(magic_header[0] & 0xFF))
  1610. X      || (getc(stdin)!=(magic_header[1] & 0xFF))) {
  1611. X        ulog(0, "input file not in compressed format");
  1612. X        exit(1);
  1613. X    }
  1614. X    maxbits = getc(stdin);  /* set -b from file */
  1615. X    block_compress = maxbits & BLOCK_MASK;
  1616. X    maxbits &= BIT_MASK;
  1617. X    maxmaxcode = ((code_int)1) << maxbits;
  1618. X
  1619. X    decompress();
  1620. X
  1621. X    fclose(stdout);
  1622. X    if (freopen(WKName, "r", stdin) == NULL) {
  1623. X    ulog(0, "Can't reopen uncompressed file for input");
  1624. X    return;
  1625. X    }
  1626. X    unbatch(NULL);
  1627. X}
  1628. X
  1629. X#undef exit
  1630. Xstatic /*volatile*/ void
  1631. Xnews_exit(int stat)
  1632. X{
  1633. X    chdir(homedir);
  1634. X    exit(stat);
  1635. X}
  1636. X
  1637. X/*
  1638. X *  When debugging RNews, this copied the input file to somewhere else to save
  1639. X *  it.
  1640. X */
  1641. X
  1642. Xvoid
  1643. Xcopy_uualtspool()
  1644. X{
  1645. X    char *ident = MakeConfigPath(UUALTSPOOL, "altseqno");
  1646. X    FILE *fi;
  1647. X    int seqno = 0;
  1648. X    int error = 0;
  1649. X    char buf[32];
  1650. X
  1651. X    if (fi = fopen(ident, "r+")) {
  1652. X    fscanf(fi, "%d", &seqno);
  1653. X    fclose(fi);
  1654. X    }
  1655. X    if (fi = fopen(ident, "w")) {
  1656. X    fprintf(fi, "%d\n", seqno + 1);
  1657. X    fclose(fi);
  1658. X    } else {
  1659. X    ulog(-1, "Unable to update %s\n", ident);
  1660. X    }
  1661. X
  1662. X    sprintf(buf, "ND.%d", seqno);
  1663. X    ident = MakeConfigPath(UUALTSPOOL, buf);
  1664. X
  1665. X    if (fi = fopen(ident, "w")) {
  1666. X    int n;
  1667. X
  1668. X    while ((n = fread(TmpBuf, 1, sizeof(TmpBuf), stdin)) > 0) {
  1669. X        if (fwrite(TmpBuf, 1, n, fi) != n) {
  1670. X        ulog(-1, "Error writing to alternate spool!");
  1671. X        error = 1;
  1672. X        break;
  1673. X        }
  1674. X    }
  1675. X    fclose(fi);
  1676. X
  1677. X    /*
  1678. X     *  if error use stdin.  If re-openning of ident fails use stdin.
  1679. X     */
  1680. X
  1681. X    rewind(stdin);
  1682. X    if (error == 0)
  1683. X        freopen(ident, "r", stdin);
  1684. X    }
  1685. X}
  1686. X
  1687. END_OF_FILE
  1688. if test 21274 -ne `wc -c <'uucp2/src/news/rnews.c'`; then
  1689.     echo shar: \"'uucp2/src/news/rnews.c'\" unpacked with wrong size!
  1690. fi
  1691. # end of 'uucp2/src/news/rnews.c'
  1692. fi
  1693. echo shar: End of archive 9 \(of 12\).
  1694. cp /dev/null ark9isdone
  1695. MISSING=""
  1696. for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
  1697.     if test ! -f ark${I}isdone ; then
  1698.     MISSING="${MISSING} ${I}"
  1699.     fi
  1700. done
  1701. if test "${MISSING}" = "" ; then
  1702.     echo You have unpacked all 12 archives.
  1703.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1704. else
  1705.     echo You still need to unpack the following archives:
  1706.     echo "        " ${MISSING}
  1707. fi
  1708. ##  End of shell archive.
  1709. exit 0
  1710. -- 
  1711. Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
  1712. Mail comments to the moderator at <amiga-request@cs.odu.edu>.
  1713. Post requests for sources, and general discussion to comp.sys.amiga.
  1714.